package orbito.entity;

import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.Shape;
import java.awt.geom.AffineTransform;
import java.awt.geom.Ellipse2D;
import java.util.LinkedList;
import java.util.List;

import orbito.GameSettings;
import orbito.graphics.ViewFocus;
import orbito.graphics.Viewport;
import orbito.physics.motion.Actor;
import orbito.util.GfxUtils;
import orbito.util.Vec2;

public class Planetoid extends Actor implements ViewFocus {
	
	// The radius of this planetoid.
	double radius;
	
	// The inner fill and outer border colors.
	Color innerColor, outerColor;
	
	// The trail of this planetoid.
	Trail trail;
	
	// The orbital parent of this planetoid, if any. Its immediate planetoid about which it orbits.
	Planetoid orbitalParent;
	
	public Planetoid(String name, Vec2 pos, Vec2 vel, double mass, double radius, Color innerColor, Color outerColor) {
		super(pos, vel, 0.0, 0.0, mass, 1.0);
		setName(name);
		
		this.radius = radius;
		this.innerColor = innerColor;
		this.outerColor = outerColor;
		
		trail = new Trail(1500);
	}
	
	public void render(Graphics2D g, double t, double dt) {
		AffineTransform tr = g.getTransform();
		
		// Translate to our position.
		g.translate(getPosition().x, getPosition().y);
		g.scale(radius, radius);
		
		// The planetoid's shape is simply an ellipse.
		Shape shape = new Ellipse2D.Double(-1, -1, 2, 2);
		
		// Paint the inner filled oval.
		g.setColor(innerColor);
		g.fill(shape);
		
		// Paint the outer border oval, if any.
		if (outerColor != null) {
			g.setColor(outerColor);
			g.draw(shape);
		}
		
		g.setTransform(tr);
	}
	
	public void renderInfo(Graphics2D g, Viewport viewport, AffineTransform tx, double t, double dt) {
		AffineTransform tr = g.getTransform();
		Font font = g.getFont();
		
		if (GameSettings.renderPlanetoidTrails) {
			// Render trail.
			g.setColor(innerColor);
			trail.renderInfo(g, viewport, tx, t, dt);
		} else {
			trail.clearPoints();
		}
		
		if (GameSettings.planetoidInfoDetail > 0) {
			Vec2 tf = getPosition().transform(tx);
			g.translate(tf.x, tf.y);
			
			// The planetoid's marker shape.
			Shape shape = new Ellipse2D.Double(-2.5, -2.5, 5, 5);
			
			// Render planetoid marker.
			g.setColor(getInnerColor());
			g.fill(shape);
			
			// Paint info text.
			if (GameSettings.planetoidInfoDetail > 1) {
				g.setFont(new Font("SansSerif", Font.PLAIN, 10));
				int h = g.getFontMetrics().getHeight();
				
				// Move to offset.
				g.translate(5, -5);
				
				// Render info with a small font.
				GfxUtils.drawTextWithBackground(g, getName(), Color.MAGENTA, Color.BLACK, 0, 0, GfxUtils.TEXT_UR);
				
				if (GameSettings.planetoidInfoDetail > 2) {
					g.translate(0, h);
					g.setColor(Color.MAGENTA);
					String mass = String.format("Speed: %.0f m/s", getVelocity().length());
					GfxUtils.drawTextWithBackground(g, mass, Color.MAGENTA, Color.BLACK, 0, 0, GfxUtils.TEXT_UR);
				}
			}
		}
		
		g.setFont(font);
		g.setTransform(tr);
	}
	
	public void step(double t, double dt) {
		// Add position to trail.
		if (orbitalParent != null) {
			trail.addPoint(getPosition(), orbitalParent.getVelocity().sub(getVelocity()));
		} else {
			trail.addPoint(getPosition(), getVelocity());
		}
	}
	
	public double getRadius() {
		return this.radius;
	}
	
	public void setRadius(double radius) {
		this.radius = radius;
	}
	
	public Color getInnerColor() {
		return this.innerColor;
	}
	
	public void setInnerColor(Color innerColor) {
		this.innerColor = innerColor;
	}
	
	public Color getOuterColor() {
		return this.outerColor;
	}
	
	public void setOuterColor(Color outerColor) {
		this.outerColor = outerColor;
	}
	
	public String toString() {
		return String.format("Planetoid(name '%s', pos %s, radius %s", getName(), getPosition(), getRadius());
	}
	
	public Planetoid getOrbitalParent() {
		return orbitalParent;
	}
	
	public void setOrbitalParent(Planetoid parent) {
		this.orbitalParent = parent;
	}
	
	// -------------------------------------------
	// ViewFocus Interface.
	
	public String getFocusName() {
		return getName();
	}
	
	public Vec2 getFocusPosition() {
		return getPosition();
	}
	
	public List<ViewFocus> getFocusChildren() {
		return new LinkedList<ViewFocus>();
	}
}
